
/* copyright (c) 1996, 1997, 1998, 1999 William R. Pearson and the
   U. of Virginia */

/* $Name: fasta34t11d4 $ - $Id: p_showalign.c,v 1.12 2002/06/23 17:52:42 wrp Exp $ */

/* manshowalign.c - show sequence alignments in pvcomplib */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef PVM_SRC
#include "pvm3.h"
#endif
#ifdef MPI_SRC
#include "mpi.h"
#endif

#include "defs.h"
#include "msg.h"
#include "structs.h"
#include "param.h"

#include "p_mw.h"

#ifdef PVM_SRC
extern int pinums[];
#endif

extern void cal_coord(int n0, int n1, long sq0off, long loffset,
		      struct a_struct *aln);

void do_show(FILE *fp, int n0, int n1, int score,
	     char *name0, char *name1, int nml,
	     struct mngmsg m_msg, struct pstruct pst, char *seqc0,
	     char *seqc1, int nc, float percent, float gpercent, int lc,
	     struct a_struct *aln, long loffset);

extern void discons(FILE *fd, struct mngmsg m_msg, struct pstruct pst,
		    char *seqc0, char *seqc1, int nc, 
		    int n0, int n1, char *name0, char *name1, int nml,
		    struct a_struct aln, long loffset);

extern void disgraph(FILE *fd, int n0, int n1,
		     float percent, int score,
		     int min0, int min1, int max0, int max1,
		     char *name0, char *name1, int nml, int llen);

extern double zs_to_bit(float, int, int);

#ifndef A_MARK
#define A_MARK ">>"
#endif

void showalign (FILE *fp, unsigned char *aa0,
		struct beststr **bptr, int nbest,int qlib, struct mngmsg m_msg,
		struct pstruct pst, char *gstring2)
{
  char bline[200], *bp, fmt[40];
  char name0[80], name1[200];
  int istart = 0, istop, i = 0, ib, n1tot;
  struct stage2_str liblist;
  struct beststr *bbp;
  struct qmng_str qm_msg;
  int sw_score;
  int nc, lc, nml;
  float percent, gpercent;
  char *seqc0, *seqc1;
#ifdef MPI_SRC
  int int_msg_b[10];
  MPI_Status mpi_status;
#endif

  qm_msg.n0 = m_msg.n0;
  strncpy(qm_msg.libstr,m_msg.libstr,sizeof(qm_msg.libstr));

  if (m_msg.markx < 10) nml = m_msg.nmlen; else nml=12;

  if (strlen(m_msg.libstr) > (size_t)0)
    if (*m_msg.libstr=='>') strncpy(name0,&m_msg.libstr[1],(size_t)nml);
    else strncpy(name0,m_msg.libstr,nml);
  else
    strncpy(name0,m_msg.tname,nml);
  name0[nml]='\0';
  if ((bp=strchr(name0,' '))!=NULL) *bp='\0';

  if (m_msg.revcomp) name0[nml-1]='-';

  if (m_msg.markx==4) m_msg.aln.llen = 50;

  sprintf(fmt,"%s%%-%ds (%%d %s)\n",A_MARK,m_msg.aln.llen-5,m_msg.sqnam);

  if (m_msg.markx < 10) fprintf(fp,"\n");

  if ((bp = strchr (m_msg.libstr, '\n')) != NULL) *bp = '\0';

  /*  fprintf (fp, "%3d >%s\n", qlib,m_msg.libstr); */

  if (m_msg.ashow < 0) m_msg.ashow = m_msg.nshow;
  istart = 0; 
  istop = min(min(nbest,m_msg.ashow),m_msg.nshow);

  for (ib=istart; ib<istop; ib++) {
    bbp = bptr[ib];
    if (pst.zsflag >= 0 && bbp->escore > m_msg.e_cut) break;

    /* we have a sequence that we need an alignment for -
       send a message to the appropriate worker to produce an alignment 
       qm_msg.slist == 1  -> one alignment
       qm_msg.s_func == 2 -> use the alignment function
       send mngmsg (MSEQTYPE)
       then send number of sequence to be aligned
    */

    qm_msg.slist = 1;
    qm_msg.s_func = 2;

    liblist.seqnm = bbp->seqnm;
    liblist.frame = bbp->frame;
#ifdef PVM_SRC
    pvm_initsend(PvmDataRaw);
    pvm_pkbyte((char *)&qm_msg,sizeof(struct qmng_str),1);
    pvm_send(pinums[bbp->wrkr],MSEQTYPE);

    pvm_initsend(PvmDataRaw);
    pvm_pkbyte((char *)&liblist,sizeof(struct stage2_str),1);
    pvm_send(pinums[bbp->wrkr],LISTTYPE);
#endif
#ifdef MPI_SRC
    MPI_Send(&qm_msg,sizeof(struct qmng_str),MPI_BYTE,bbp->wrkr,
	     MSEQTYPE,MPI_COMM_WORLD);
    MPI_Send(&liblist,sizeof(struct stage2_str),MPI_BYTE,bbp->wrkr,
	     LISTTYPE,MPI_COMM_WORLD);
#endif
    /* information should be sent */

    strncpy(bline,bbp->desptr->bline,m_msg.aln.llen-5);
    n1tot = (bbp->desptr->n1tot_p) ? *bbp->desptr->n1tot_p : bbp->n1;

    bline[m_msg.aln.llen-5]='\0';

    strncpy(name1,bline,sizeof(name1));

    if (m_msg.markx<=9) name1[nml]='\0';
    if ((bp = strchr(name1,' '))!=NULL) *bp = '\0';

/* print out score information; */
    
    if (m_msg.markx < 4 || m_msg.markx == 9) {
      fprintf (fp, fmt,bp=bline,n1tot);
      if (m_msg.nframe > 2) 
	fprintf (fp, "Frame: %d",bbp->frame+1);
      else if (m_msg.nframe > 1) 
	fprintf (fp, "Frame: %c",(bbp->frame? 'r': 'f'));
      else if (m_msg.qframe >= 0 && bbp->frame > 0 ) {
	  fputs("rev-comp",fp);
	  name0[nml-1]='\0';
	  strcat(name0,"-");
      }

      if (m_msg.arelv > 0)
	fprintf (fp, " %s: %3d", m_msg.alab[0],bbp->score[0]);
      if (m_msg.arelv > 1)
	fprintf (fp, " %s: %3d", m_msg.alab[1],bbp->score[1]);
      if (m_msg.arelv > 2)
	fprintf (fp, " %s: %3d", m_msg.alab[2],bbp->score[2]);
      if (pst.zsflag>=0) 
	fprintf (fp, " Z-score: %4.1f bits: %3.1f E(): %4.2g", bbp->zscore,
		 zs_to_bit(bbp->zscore,m_msg.n0,bbp->n1),bbp->escore);
      fprintf (fp, "\n");
    }
    else if (m_msg.markx==10) {
      fprintf(fp,">>%s\n",bline);
      if (m_msg.nframe != -1) 
	fprintf (fp, "; %s_frame: %d",m_msg.f_id0,bbp->frame+1);
      fprintf (fp, "; %s_%s: %3d\n", m_msg.f_id0,m_msg.alab[0],bbp->score[0]);
      if (m_msg.arelv > 1)
	fprintf (fp,"; %s_%s: %3d\n", m_msg.f_id0,m_msg.alab[1],bbp->score[1]);
      if (m_msg.arelv > 2)
	fprintf (fp,"; %s_%s: %3d\n", m_msg.f_id0,m_msg.alab[2],bbp->score[2]);
      if (pst.zsflag>=0) 
	fprintf (fp,"; %s_z-score: %4.1f\n; %s_expect %6.2g\n",
		 m_msg.f_id0,bbp->zscore,m_msg.f_id0,bbp->escore);
    }
    /*  get the sw_score, alignment  information,
        get seqc0, seqc1 */

#ifdef PVM_SRC
    pvm_recv(pinums[bbp->wrkr],ALN1TYPE);
    pvm_upkint(&nc,1,1);
    pvm_upkint(&lc,1,1);
    pvm_upkfloat(&percent,1,1);
    pvm_upkfloat(&gpercent,1,1);

    pvm_upkint(&sw_score,1,1);
    pvm_upkbyte((char *)&m_msg.aln,sizeof(struct a_struct),1);
#endif
#ifdef MPI_SRC
    MPI_Recv(int_msg_b,3,MPI_INT,bbp->wrkr,ALN1TYPE,MPI_COMM_WORLD,
	     &mpi_status);
    nc = int_msg_b[0];
    lc = int_msg_b[1];
    sw_score = int_msg_b[2];
    MPI_Recv(&percent,1,MPI_FLOAT,bbp->wrkr,ALN2TYPE,MPI_COMM_WORLD,
	     &mpi_status);
    MPI_Recv(&gpercent,1,MPI_FLOAT,bbp->wrkr,ALN2TYPE,MPI_COMM_WORLD,
	     &mpi_status);
    MPI_Recv(&m_msg.aln,sizeof(struct a_struct),MPI_BYTE,
	     bbp->wrkr,ALN3TYPE,MPI_COMM_WORLD,&mpi_status);
#endif

    cal_coord(m_msg.n0,bbp->n1,m_msg.sq0off,bbp->desptr->loffset-1,&m_msg.aln);

    if ((seqc0=(char *)calloc(nc+1,sizeof(char)))==NULL) {
      fprintf(stderr," cannot allocate seqc0[%d]\n",nc+1);
      exit(1);
    }

    if ((seqc1=(char *)calloc(nc+1,sizeof(char)))==NULL) {
      fprintf(stderr," cannot allocate seqc1[%d]\n",nc+1);
      exit(1);
    }

    /*     fprintf(stderr," waiting for seqc0/1[%d]\n",nc); */

#ifdef PVM_SRC
    pvm_recv(pinums[bbp->wrkr],ALN2TYPE);
    pvm_upkbyte(seqc0,nc,1);
    pvm_upkbyte(seqc1,nc,1);
#endif
#ifdef MPI_SRC
    MPI_Recv(seqc0,nc,MPI_BYTE,bbp->wrkr,ALN2TYPE,MPI_COMM_WORLD,&mpi_status);
    MPI_Recv(seqc1,nc,MPI_BYTE,bbp->wrkr,ALN3TYPE,MPI_COMM_WORLD,&mpi_status);
#endif

    do_show(fp, m_msg.n0, bbp->n1, sw_score, name0, name1, nml,
	    m_msg, pst, seqc0, seqc1, nc, percent, gpercent, lc, &m_msg.aln, 
	    bbp->desptr->loffset-1);

    fflush(fp);

    free(seqc0); free(seqc1);
  }
  if (fp!=stdout) fprintf(fp,"\n");
}

void do_show(FILE *fp, int n0,int n1, int score,
	     char *name0, char *name1, int nml,
	     struct mngmsg m_msg, struct pstruct pst,
	     char *seqc0, char *seqc1, int nc,
	     float percent, float gpercent, int lc,
	     struct a_struct *aln, long loffset)
{

  if (m_msg.markx == 4)
    disgraph(fp, n0, n1, percent, score,
	     aln->min0, aln->min1, aln->max0, aln->max1,
	     name0, name1, nml, aln->llen);
  else if (m_msg.markx < 10) {
    if (pst.sw_flag) fprintf(fp,"Smith-Waterman score: %d; ",score);
    else fprintf(fp,"banded Smith-Waterman score: %d; ",score);
    fprintf(fp," %6.3f%% identity (%6.3f%% ungapped) in %d %s overlap (%ld-%ld:%ld-%ld)\n",
	    percent,gpercent,lc,m_msg.sqnam,aln->d_start0,aln->d_stop0,
	    aln->d_start1,aln->d_stop1);
    discons(fp, m_msg, pst, seqc0, seqc1, nc, n0, n1,
	    name0, name1,nml, *aln, loffset);
    fputc('\n',fp);
  }
/*
  else if (m_msg.markx==9) {
    fprintf(fp,"\t%5.3f\t%5.3f\t%4d\t%4d\t%4d\t%4d\t%4d\t%3d\t%3d\n",
	    percent/100.0,gpercent/100.0,lc,
	    aln->min0+1,aln->max0,aln->min1+1,aln->max1,
	    aln->ngap_q, aln->ngap_l);
  }
*/
  else if (m_msg.markx==10) {
    if (pst.sw_flag && m_msg.arelv>0)
      fprintf(fp,"; %s_score: %d\n",m_msg.f_id1,score);
    fprintf(fp,"; %s_ident: %5.3f\n",m_msg.f_id1,percent/100.0);
    fprintf(fp,"; %s_gident: %5.3f\n",m_msg.f_id1,gpercent/100.0);
    fprintf(fp,"; %s_overlap: %d\n",m_msg.f_id1,lc);
    discons(fp, m_msg, pst, seqc0, seqc1, nc, n0, n1,
	    name0, name1, nml, *aln, loffset);
  }
}
